home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c-part1 / 5739 < prev    next >
Encoding:
Internet Message Format  |  1996-08-05  |  4.3 KB

  1. Path: newshost.cyberramp.net!news
  2. From: sinan@cyberramp.net (John Noland)
  3. Newsgroups: comp.lang.c
  4. Subject: Re: simple code, argc, argv, strcmp()
  5. Date: 21 Feb 1996 00:01:41 GMT
  6. Organization: Prose Software
  7. Message-ID: <4gdnd5$489@newshost.cyberramp.net>
  8. References: <11f7cc$17261a.3b3@daprez> <9602011151.AA04526@dxmint.cern.ch> <4g040v$7jj@maverick.tad.eds.com>
  9. NNTP-Posting-Host: ramp2-16.cyberramp.net
  10. X-Newsreader: WinVN 0.99.5
  11.  
  12. In article <4g040v$7jj@maverick.tad.eds.com>, gulleha@vaxixhp3.vaxix.slg.eds.com says...
  13.  
  14. >>int main (int argc, char **argv) {
  15. >>
  16. >>  if (!strcmp(argv[1],"-d") || !strcmp(argv[1],"-e")) {
  17. >>    Usage();
  18. >>  }
  19. >...
  20. >>
  21. >>Can someone see what's wrong with this ?
  22. >>am I not using strcmp() right ?
  23. >
  24.  
  25. I need to make the following statements just to be thorough:
  26.  
  27. 1. int strcmp(const char *s1, const char *s2);
  28. strcmp returns a value that is 
  29. < 0  if s1 is less than s2
  30. == 0 if s1 is the same as s2
  31. > 0  if s1 is greater than s2
  32.  
  33. 2. if (conditional-expression) TRUE-STATEMENT <else FALSE-STATEMENT>
  34. The conditional-expression must be of scalar type. The expression is
  35. evaluated. If the value is zero, we say that the conditional-expression
  36. is FALSE; otherwise, it is TRUE.
  37. If there is no else clause, and the conditional-expression is TRUE, 
  38. TRUE-STATEMENT is executed; otherwise, TRUE-STATEMENT is ignored.
  39.  
  40. 3. In the expression E1 || E2, both operands must be of scalar type. The
  41. result is of type int, and the result is 1 (TRUE) if either of the values
  42. of E1 or E2 are nonzero. Otherwise, the result is 0 (FALSE).
  43. E1 is evaluated first; if E1 is nonzero, E1 || E2 gives 1 (TRUE), and E2
  44. is not evaluated. This so-called "short-circuit evaluation" is true in
  45. Microsoft and Borland compilers, but is not specified by "K&R" or 
  46. ANSI. Your compiler may or may not do it this way.
  47.  
  48. 4. The unary negation operator ! converts a non-zero (TRUE) operand into
  49. zero, and a zero (FALSE) operand into 1.
  50.  
  51. 5. You will need to check the language reference that came with your 
  52. compiler to verify precedence and order of evaluation. They tend to
  53. be consistent from one to another, but they aren't specified in any
  54. official standard, so yours could be different(BLECHHH!).
  55.  
  56. How does the statement evaluate:
  57.  
  58. if argv[1] is neither "-d" or "-e"? 
  59.  
  60. 1. strcmp returns an int not equal to zero for each expression.
  61. 2. The ! operator logically negates the return value of each
  62.    strcmp, giving zero for both. Our statement is now essentially:
  63.    <if (0 || 0)>.
  64. 3. 0 || 0 gives 0. We now have <if (0)> or <if (FALSE)> 
  65.  
  66. RESULT: usage() is not called. This is an INCORRECT result!  
  67.  
  68. if argv[1] is "-d" or "-e"?
  69.  
  70. 1. One strcmp returns zero, the other returns non-zero.
  71. 2. The ! operator logically negates the return value of
  72.    each strcmp, giving zero for one and one for the other.
  73.    Our statement is now essentially: <if (1 || 0)> or 
  74.    <if (0 || 1)>.
  75. 3. 1 || 0 or 0 || 1 gives 1. We now have <if (1)>.
  76.  
  77. RESULT: usage() is called. This is an incorrect result!
  78.  
  79. if argv[1] is equal to "-d" and "-e"? 
  80.  
  81. Wait a minute! Is this combination possible? Do you see the problem
  82. with this? The same variable cannot possibly have two different 
  83. values at the same time. 
  84.  
  85. To ease the illustration of this and rid strcmp from the discussion, 
  86. let's use an int in simplified conditional statements. Your statement 
  87. above would look something like this (though not exactly, I'll get to 
  88. that in a minute!):
  89.  
  90. int number;
  91. ...
  92.        if ((number != 6) || (number != 9)) some_function();
  93.  
  94.  
  95. This a common mistake in most programming languages (not just C). The 
  96. problem is that at least one of the simple conditions will always be 
  97. true; number will always either not contain a 6 or not contain a 9, or 
  98. not contain either one. Thus, the compound condition is always true. 
  99. This isn't true with the strcmp example above. Why is that, do you 
  100. reckon? Here's a hint, I think you can figure it out yourself:
  101.     if (!(number == 6) || !(number == 9)) some_function();
  102.  
  103. The "moral" of all of this is a lesson in boolean algebra, which is:
  104. When negating conditions separated by ||: if !(exp1 || exp2), the 
  105. stated conditions become: if (!exp1 AND !exp2)...
  106.  
  107. Hence,  
  108.    if !(strcmp(argv[1], "-d") || strcmp(argv[1], "-e") usage();
  109. or
  110.    if (!strcmp(argv[1], "-d") && !strcmp(argv[1], "-e") usage(); 
  111.  
  112. would be solutions that do what you desire. 
  113.  
  114. Sorry this is such a long answer, but I've found that only the real
  115. gurus are allowed to be terse in this group.
  116.  
  117. -John
  118.  
  119.